import axios, { AxiosInstance, AxiosResponse } from 'axios';
import { PrometheusQuery, PrometheusRangeQuery, PrometheusResponse, PrometheusMetric } from '../types/index';
import config from '@config/index';
import logger from '@utils/logger';

export interface AlertmanagerAlert {
  annotations: Record<string, string>;
  endsAt: string;
  fingerprint: string;
  generatorURL: string;
  labels: Record<string, string>;
  startsAt: string;
  status: {
    inhibitedBy: string[];
    silencedBy: string[];
    state: 'active' | 'suppressed' | 'unprocessed';
  };
  updatedAt: string;
}

export interface AlertmanagerResponse {
  status: string;
  data: AlertmanagerAlert[];
}

class PrometheusService {
  private prometheusClient: AxiosInstance;
  private alertmanagerClient: AxiosInstance;

  constructor() {
    // Prometheus 客户端
    this.prometheusClient = axios.create({
      baseURL: config.env.PROMETHEUS_URL,
      timeout: 30000,
      headers: {
        'Content-Type': 'application/json',
      },
    });

    // Alertmanager 客户端
    this.alertmanagerClient = axios.create({
      baseURL: config.env.ALERTMANAGER_URL,
      timeout: 30000,
      headers: {
        'Content-Type': 'application/json',
      },
    });

    this.setupInterceptors();
  }

  /**
   * 设置请求拦截器
   */
  private setupInterceptors(): void {
    // Prometheus 响应拦截器
    this.prometheusClient.interceptors.response.use(
      (response) => response,
      (error) => {
        logger.error('Prometheus API error:', error as Error);
        throw new Error(`Prometheus API error: ${error.message}`);
      }
    );

    // Alertmanager 响应拦截器
    this.alertmanagerClient.interceptors.response.use(
      (response) => response,
      (error) => {
        logger.error('Alertmanager API error:', error as Error);
        throw new Error(`Alertmanager API error: ${error.message}`);
      }
    );
  }

  /**
   * 执行即时查询
   */
  async query(queryParams: PrometheusQuery): Promise<PrometheusResponse> {
    try {
      const response: AxiosResponse<PrometheusResponse> = await this.prometheusClient.get('/api/v1/query', {
        params: queryParams,
      });

      return response.data;
    } catch (error) {
      logger.error('Failed to execute Prometheus query:', error as Error);
      throw error;
    }
  }

  /**
   * 执行范围查询
   */
  async queryRange(queryParams: PrometheusRangeQuery): Promise<PrometheusResponse> {
    try {
      const response: AxiosResponse<PrometheusResponse> = await this.prometheusClient.get('/api/v1/query_range', {
        params: queryParams,
      });

      return response.data;
    } catch (error) {
      logger.error('Failed to execute Prometheus range query:', error as Error);
      throw error;
    }
  }

  /**
   * 获取所有标签
   */
  async getLabels(): Promise<string[]> {
    try {
      const response = await this.prometheusClient.get('/api/v1/labels');
      return response.data.data || [];
    } catch (error) {
      logger.error('Failed to get Prometheus labels:', error as Error);
      throw error;
    }
  }

  /**
   * 获取标签值
   */
  async getLabelValues(labelName: string): Promise<string[]> {
    try {
      const response = await this.prometheusClient.get(`/api/v1/label/${labelName}/values`);
      return response.data.data || [];
    } catch (error) {
      logger.error(`Failed to get values for label ${labelName}:`, error as Error);
      throw error;
    }
  }

  /**
   * 获取指标列表
   */
  async getMetrics(): Promise<string[]> {
    try {
      const response = await this.prometheusClient.get('/api/v1/label/__name__/values');
      return response.data.data || [];
    } catch (error) {
      logger.error('Failed to get Prometheus metrics:', error as Error);
      throw error;
    }
  }

  /**
   * 获取系统健康指标
   */
  async getSystemHealth(): Promise<{
    cpuUsage: number;
    memoryUsage: number;
    diskUsage: number;
    networkIO: number;
  }> {
    try {
      const queries = {
        cpu: '100 - (avg by (instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)',
        memory: '(1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100',
        disk: '(1 - (node_filesystem_avail_bytes / node_filesystem_size_bytes)) * 100',
        network: 'rate(node_network_receive_bytes_total[5m]) + rate(node_network_transmit_bytes_total[5m])',
      };

      const [cpuResult, memoryResult, diskResult, networkResult] = await Promise.all([
        this.query({ query: queries.cpu }),
        this.query({ query: queries.memory }),
        this.query({ query: queries.disk }),
        this.query({ query: queries.network }),
      ]);

      return {
        cpuUsage: this.getAverageValue(cpuResult.data.result),
        memoryUsage: this.getAverageValue(memoryResult.data.result),
        diskUsage: this.getAverageValue(diskResult.data.result),
        networkIO: this.getAverageValue(networkResult.data.result),
      };
    } catch (error) {
      logger.error('Failed to get system health metrics:', error as Error);
      throw error;
    }
  }

  /**
   * 获取应用性能指标
   */
  async getApplicationMetrics(): Promise<{
    httpRequestRate: number;
    httpErrorRate: number;
    responseTime: number;
    activeConnections: number;
  }> {
    try {
      const queries = {
        requestRate: 'sum(rate(http_requests_total[5m]))',
        errorRate: 'sum(rate(http_requests_total{status=~"5.."}[5m])) / sum(rate(http_requests_total[5m])) * 100',
        responseTime: 'histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))',
        connections: 'sum(node_netstat_Tcp_CurrEstab)',
      };

      const [requestResult, errorResult, responseResult, connectionResult] = await Promise.all([
        this.query({ query: queries.requestRate }),
        this.query({ query: queries.errorRate }),
        this.query({ query: queries.responseTime }),
        this.query({ query: queries.connections }),
      ]);

      return {
        httpRequestRate: this.getAverageValue(requestResult.data.result),
        httpErrorRate: this.getAverageValue(errorResult.data.result),
        responseTime: this.getAverageValue(responseResult.data.result),
        activeConnections: this.getAverageValue(connectionResult.data.result),
      };
    } catch (error) {
      logger.error('Failed to get application metrics:', error as Error);
      throw error;
    }
  }

  /**
   * 获取活跃告警
   */
  async getActiveAlerts(): Promise<AlertmanagerAlert[]> {
    try {
      const response: AxiosResponse<AlertmanagerResponse> = await this.alertmanagerClient.get('/api/v1/alerts');
      
      if (response.data.status === 'success') {
        return response.data.data.filter(alert => alert.status.state === 'active');
      }
      
      return [];
    } catch (error) {
      logger.error('Failed to get active alerts from Alertmanager:', error as Error);
      throw error;
    }
  }

  /**
   * 获取告警规则
   */
  async getAlertRules(): Promise<any[]> {
    try {
      const response = await this.prometheusClient.get('/api/v1/rules');
      
      if (response.data.status === 'success') {
        return response.data.data.groups || [];
      }
      
      return [];
    } catch (error) {
      logger.error('Failed to get alert rules:', error as Error);
      throw error;
    }
  }

  /**
   * 静默告警
   */
  async silenceAlert(alertId: string, duration: number, comment: string): Promise<void> {
    try {
      const silenceData = {
        matchers: [
          {
            name: 'alertname',
            value: alertId,
            isRegex: false,
          },
        ],
        startsAt: new Date().toISOString(),
        endsAt: new Date(Date.now() + duration * 60 * 1000).toISOString(),
        comment,
        createdBy: 'devops-smart-bot',
      };

      await this.alertmanagerClient.post('/api/v1/silences', silenceData);
      logger.info(`Alert ${alertId} silenced for ${duration} minutes`);
    } catch (error) {
      logger.error(`Failed to silence alert ${alertId}:`, error as Error);
      throw error;
    }
  }

  /**
   * 检查 Prometheus 连接状态
   */
  async checkHealth(): Promise<{ prometheus: boolean; alertmanager: boolean }> {
    const health = {
      prometheus: false,
      alertmanager: false,
    };

    try {
      // 检查 Prometheus
      const prometheusResponse = await this.prometheusClient.get('/-/healthy', { timeout: 5000 });
      health.prometheus = prometheusResponse.status === 200;
    } catch (error) {
      logger.warn('Prometheus health check failed:', error as Error);
    }

    try {
      // 检查 Alertmanager
      const alertmanagerResponse = await this.alertmanagerClient.get('/-/healthy', { timeout: 5000 });
      health.alertmanager = alertmanagerResponse.status === 200;
    } catch (error) {
      logger.warn('Alertmanager health check failed:', error as Error);
    }

    return health;
  }

  /**
   * 获取时间序列数据
   */
  async getTimeSeriesData(query: string, start: Date, end: Date, step: string = '60s'): Promise<PrometheusMetric[]> {
    try {
      const response = await this.queryRange({
        query,
        start: Math.floor(start.getTime() / 1000).toString(),
        end: Math.floor(end.getTime() / 1000).toString(),
        step,
      });

      return response.data.result;
    } catch (error) {
      logger.error('Failed to get time series data:', error as Error);
      throw error;
    }
  }

  /**
   * 获取实例列表
   */
  async getInstances(): Promise<string[]> {
    try {
      const response = await this.query({ query: 'up' });
      const instances = new Set<string>();
      
      response.data.result.forEach(metric => {
        if (metric.metric.instance) {
          instances.add(metric.metric.instance);
        }
      });
      
      return Array.from(instances);
    } catch (error) {
      logger.error('Failed to get instances:', error as Error);
      throw error;
    }
  }

  /**
   * 获取服务列表
   */
  async getServices(): Promise<string[]> {
    try {
      const response = await this.query({ query: 'up' });
      const services = new Set<string>();
      
      response.data.result.forEach(metric => {
        if (metric.metric.job) {
          services.add(metric.metric.job);
        }
      });
      
      return Array.from(services);
    } catch (error) {
      logger.error('Failed to get services:', error as Error);
      throw error;
    }
  }

  /**
   * 辅助方法：计算指标平均值
   */
  private getAverageValue(metrics: PrometheusMetric[]): number {
    if (!metrics || metrics.length === 0) {
      return 0;
    }

    const values = metrics
      .map(metric => metric.value?.[1])
      .filter(value => value !== undefined)
      .map(value => parseFloat(value as string))
      .filter(value => !isNaN(value));

    if (values.length === 0) {
      return 0;
    }

    return values.reduce((sum, value) => sum + value, 0) / values.length;
  }

  /**
   * 辅助方法：格式化指标数据
   */
  formatMetricData(metrics: PrometheusMetric[]): Array<{
    labels: Record<string, string>;
    value: number;
    timestamp: number;
  }> {
    return metrics.map(metric => ({
      labels: metric.metric,
      value: metric.value ? parseFloat(metric.value[1]) : 0,
      timestamp: metric.value ? metric.value[0] : Date.now() / 1000,
    }));
  }
}

export default new PrometheusService();